package cn.kgc.common.exceptionhandler;

import cn.kgc.common.constant.SystemConstant;
import cn.kgc.vo.Result;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;

/**
 * <p>添加描述信息</p>
 *
 * @author 石浩杰
 * @since 2022年09月24日 10:34
 *
 * SpringMVC 处理异常:全局异常 局部异常@ExceptionHandler
 */
//@ControllerAdvice("cn.kgc.controller")
public class GlobalExceptionAdvice {

    @Resource
    private ExceptionCodeConfig exceptionCodeConfig;

    /**
     * JSR303服务器端验证，传入的参数是一个实体类，实体类的属性验证失败触发MethodArgumentNotValidException异常
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public Result handlerMethodArgumentNotValidException(
            HttpServletRequest request,
            MethodArgumentNotValidException exception){
        String uri=request.getRequestURI();
        //获得验证失败的信息
        List<ObjectError> objectErrorList=exception.getBindingResult().getAllErrors();
        String defaultMessage="";//错误信息
        for (ObjectError objectError : objectErrorList) {
            String errorMessage=objectError.getDefaultMessage();//验证失败的message属性值
            defaultMessage+=errorMessage+";";
        }
        Result result=Result.builder().code(SystemConstant.EXCEPTION_CODE)
                .data(null)
                .requestURL(uri)
                .message(defaultMessage).build();//封装result对象
        return result;
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public Result handleConstraintViolationException(HttpServletRequest request,
                                                     ConstraintViolationException exception){
        String uri=request.getRequestURI();//请求地址
        String message=exception.getMessage();//获得验证失败的所有错误信息
        Result result=Result.builder().code(SystemConstant.EXCEPTION_CODE)//构建result对象
                .requestURL(uri)
                .data(null)
                .message(message).build();
        return result;
    }


    @ExceptionHandler({HttpException.class})
    public ResponseEntity handleHttpException(HttpServletRequest request,
                                              HttpException httpException){
        String uri=request.getRequestURI(); //获得请求的地址
        int httpExceptionCode=httpException.getCode(); //自定义的异常编码

        String message=exceptionCodeConfig.getExceptionMessage(httpExceptionCode);
        //获得异常的信息，将异常的信息封装成Result对象
        Result result=
                Result.builder().requestURL(uri).message(message).code(httpExceptionCode).data(null).build();
        //返回响应体:result对象 格式 状态码
        /*int statusCode=httpException.httpStatusCode;
        HttpStatus httpStatus=HttpStatus.resolve(statusCode);*/
        HttpHeaders httpHeaders=new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpStatus status=HttpStatus.OK;
        //封装响应体
        ResponseEntity responseEntity=new ResponseEntity(result,httpHeaders,status);
        return responseEntity;
    }

    @ExceptionHandler({Exception.class})
    public ResponseEntity handleException(HttpServletRequest request,
                                          Exception exception){
        String uri=request.getRequestURI(); //获得请求地址
        String exceptionMessage=
            exceptionCodeConfig.getExceptionMessage(SystemConstant.EXCEPTION_CODE);
        //创建result对象，包含了异常信息
        Result result=Result.builder().code(SystemConstant.EXCEPTION_CODE).data(null).requestURL(uri).message(exceptionMessage).build();
        //封装响应信息:响应的状态码 响应的数据格式 响应的数据x
        HttpStatus httpStatus=HttpStatus.OK;
        HttpHeaders httpHeaders=new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        ResponseEntity responseEntity=new ResponseEntity(result,httpHeaders,httpStatus);
        return responseEntity;
    }
}
